﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace WpUserControls.UserControls
{
    public partial class PinInputBox : UserControl
    {
        public PinInputBox()
        {
            InitializeComponent();

            PinTextBox.Text = string.Empty;

            // default to 4 chars long PIN
            this.Length = 4;
            
            this.Loaded += new RoutedEventHandler(PinInputBox_Loaded);
            this.Tap += new EventHandler<GestureEventArgs>(PinInputBox_Tap);
            this.PinTextBox.TextChanged += new TextChangedEventHandler(PinTextBox_TextChanged);
        }

        private List<PinChar> _chars = new List<PinChar>();

        [Browsable(true)]
        public int Length
        {
            get
            {
                return _chars.Count;
            }
            set
            {
                _chars.Clear();
                for (var i = 0; i < value; i++)
                {
                    _chars.Add(new PinChar { Visibility = System.Windows.Visibility.Collapsed, Size = _pinBoxSize, });
                }

                PinTextBox.MaxLength = value;
            }
        }

        [Browsable(true)]
        public string Text
        {
            get
            {
                return PinTextBox.Text;
            }
            set
            {
                PinTextBox.Text = value.Truncate(0, PinTextBox.MaxLength);
                foreach (var pinChar in _chars)
                {
                    pinChar.Visibility = _chars.IndexOf(pinChar) >= PinTextBox.Text.Length ? Visibility.Collapsed : Visibility.Visible;
                }
            }
        }

        public InputScope InputScope
        {
            get
            {
                return PinTextBox.InputScope;
            }
            set
            {
                PinTextBox.InputScope = value;
            }
        }

        private int _pinBoxSize = 80;
        [Browsable(true)]
        public int PinBoxSize
        {
            get
            {
                return _pinBoxSize;
            }
            set
            {
                _pinBoxSize = value;
                _chars.ForEach(x => x.Size = value);
            }
        }

        private CornerRadius _pinBoxCornerRadius = new CornerRadius(12);
        [Browsable(true)]
        public CornerRadius PinBoxCornerRadius
        {
            get
            {
                return _pinBoxCornerRadius;
            }
            set
            {
                _pinBoxCornerRadius = value;
                _chars.ForEach(x => x.CornerRadius = value);
            }
        }

        private Thickness _pinBoxMargin = new Thickness(10);
        [Browsable(true)]
        public Thickness PinBoxMargin
        {
            get
            {
                return _pinBoxMargin;
            }
            set
            {
                _pinBoxMargin = value;
                _chars.ForEach(x => x.Margin = value);
            }
        }

        private Brush _pinBoxBackground = new SolidColorBrush(Colors.White);
        [Browsable(true)]
        public Brush PinBoxBackground
        {
            get
            {
                return _pinBoxBackground;
            }
            set
            {
                _pinBoxBackground = value;
                _chars.ForEach(x => x.Background = value);
            }
        }

        void PinTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            foreach (var pinChar in _chars)
            {
                pinChar.Visibility = _chars.IndexOf(pinChar) >= PinTextBox.Text.Length ? Visibility.Collapsed : Visibility.Visible;
            }

            if (TextChanged != null)
            {
                TextChanged(this, e);
            }
        }

        public event TextChangedEventHandler TextChanged;

        void PinInputBox_Tap(object sender, GestureEventArgs e)
        {
            PinTextBox.Focus();
        }

        void PinInputBox_Loaded(object sender, RoutedEventArgs e)
        {
            PinChars.ItemsSource = _chars;
        }

        public new void Focus()
        {
            PinTextBox.Focus();
        }
    }

    public class PinChar : INotifyPropertyChanged
    {
        public string Char { get; set; }

        private Visibility _visibility = Visibility.Visible;
        public Visibility Visibility
        {
            get
            {
                return _visibility;
            }
            set
            {
                _visibility = value;
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Visibility"));
            }
        }

        private int _size = 80;
        public int Size
        {
            get
            {
                return _size;
            }
            set
            {
                _size = value;
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("PinBoxSize"));
            }
        }

        private CornerRadius _cornerRadius = new CornerRadius(12);
        public CornerRadius CornerRadius
        {
            get
            {
                return _cornerRadius;
            }
            set
            {
                _cornerRadius = value;
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("PinBoxCornerRadius"));
            }
        }

        private Thickness _margin = new Thickness(10);
        public Thickness Margin
        {
            get
            {
                return _margin;
            }
            set
            {
                _margin = value;
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("PinBoxMargin"));
            }
        }

        private Brush _background = new SolidColorBrush(Colors.White);
        public Brush Background
        {
            get
            {
                return _background;
            }
            set
            {
                _background = value;
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Background"));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

}
